/* 
 * File:   server_Grafico.h
 * Author: nahuel
 *
 * Created on June 12, 2013, 7:24 PM
 */

#ifndef GRAFICO_H
#define	GRAFICO_H

#include <gtkmm-3.0/gtkmm/drawingarea.h>
#include <gtkmm-3.0/gtkmm/builder.h>
#include <list>
#include <time.h>


typedef struct {
    double x;
    double y;
} DataPoint;

/**
 * @class Clase encargada de realizar el grafico de bytes almacenados en funcion
 * del tiempo, en la interfaz grafica del servidor.
 */

class Grafico : public Gtk::DrawingArea {
    private:
        Gtk::DrawingArea* _drawingArea;
        unsigned int _refreshRate;  // En segundos
        std::list<DataPoint*> _listDatos;
        std::string _pathAuServidor;
        time_t _startTime;
        
        /**
         * @brief Crea y agrega a la lista de datos un nuevo par, donde x es el
         * instante actual (relativo al instante inicial) e y es el tamanho en
         * bytes actual del repositorio del servidor.
         */
        void ReadNewDataPoint();
        
        /**
         * @brief Formateador de labels del eje X.
         * @param x Instante de tiempo en segundos (relativo al instante inicial).
         * @return Cadena de caracteres con el label formateado.
         */
        std::string XAxisFormatter(double x);
        
        
        /**
         * @brief Formateador de labels del eje Y.
         * @param y Tamanho en bytes del repositorio para algun instante dado.
         * @return Cadena de caracteres con el label formateado.
         */
        std::string YAxisFormatter(double y);        
        
        /**
         * @brief Dibuja en el DrawingArea el label del eje X correspondiente en
         * la posicion requerida, centrado segun el ancho del texto.
         * @param cr Cairo Context del DrawingArea donde dibujar
         * @param label El label a escribir
         * @param x Posicion x donde escribir el label
         * @param y Posicion y donde escribir el label
         */
        void WriteXAxisLabel(const Cairo::RefPtr<Cairo::Context>& cr, 
                             const std::string& label, double x, double y);
        
        /**
         * @brief Dibuja en el DrawingArea el label del eje Y correspondiente en
         * la posicion requerida.
         * @param cr Cairo Context del DrawingArea donde dibujar
         * @param label El label a escribir
         * @param x Posicion x donde escribir el label
         * @param y Posicion y donde escribir el label
         */
        void WriteYAxisLabel(const Cairo::RefPtr<Cairo::Context>& cr, 
                             const std::string& label, double x, double y);
        
        /**
         * @brief Calcula el label correspondiente para la i-esima division del
         * eje X.
         * @param i Numero de division del eje X.
         * @param maxX Maximo valor definido para la escala actual del eje X.
         * @param minX Minimo valor definido para la escala actual del eje X.
         * @return Cadena de caracteres con el label formateado.
         */
        std::string GetXAxisLabel(unsigned int i, double maxX, double minX);
        
        /**
         * @brief Calcula el label correspondiente para la i-esima division del
         * eje Y.
         * @param i Numero de division del eje Y.
         * @param maxY Maximo valor definido para la escala actual del eje Y.
         * @param minY Minimo valor definido para la escala actual del eje Y.
         * @return Cadena de caracteres con el label formateado.
         */
        std::string GetYAxisLabel(unsigned int i, double maxY, double minY);
        
        /**
         * @brief Calcula la coordenada X del DrawingArea que le corresponde a 
         * un valor determinado de la dimension X.
         * @param transformThis Valor a transformar.
         * @param xAxisBeg Coordenada X del DrawingArea donde comienza el eje X.
         * @param xAxisEnd Coordenada X del DrawingArea donde termina el eje X.
         * @param minX Minimo valor definido para la escala actual del eje X.
         * @param maxX Maximo valor definido para la escala actual del eje X.
         * @return Coordenada X transformada.
         */
        double TransformX(double transformThis, double xAxisBeg, 
                          double xAxisEnd, double minX, double maxX);
        
        /**
         * @brief Calcula la coordenada Y del DrawingArea que le corresponde a 
         * un valor determinado de la dimension Y.
         * @param transformThis Valor a transformar.
         * @param yAxisBeg Coordenada Y del DrawingArea donde comienza el eje Y.
         * @param yAxisEnd Coordenada Y del DrawingArea donde termina el eje Y.
         * @param minY Minimo valor definido para la escala actual del eje Y.
         * @param maxY Maximo valor definido para la escala actual del eje Y.
         * @return Coordenada Y transformada.
         */
        double TransformY(double transformThis, double yAxisBeg, 
                          double yAxisEnd, double minY, double maxY);        
        
    protected:
        virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
        bool on_timeout();
        
    public:
         /*
         * Parametros necesarios para crear el objeto a partir del archivo
         * .glade
         */
        Grafico(BaseObjectType* cobject,
                const Glib::RefPtr<Gtk::Builder>& refGlade);
        virtual ~Grafico();
};

#endif	/* GRAFICO_H */

